package com.task.core.task;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.task.common.utils.date.DateConstants;
import com.task.common.utils.date.DateUtil;
import com.task.core.dto.request.info.HistoryDataSearchInfo;
import com.task.core.service.DataPreAvailableService;
import com.task.core.service.SendHistoryService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import com.task.common.core.redis.RedisCache;
import com.task.common.utils.SystemFunctionUtil;
import com.task.common.utils.constants.RedisConstants;
import com.task.core.domain.info.MissionSuccessRedisMap;
import com.task.core.mapper.DataOperationMapper;
import com.task.core.mapper.MissionMapper;
import com.task.core.service.impl.DataOperationServiceImpl;
import com.task.core.task.into.DataIncrementCodeGroupInfo;
import com.task.core.task.into.DataIncrementInfo;
import com.task.core.task.into.MissionChangeNotNormalInfo;

/**
 * @author 迪迦.
 * @date 2025/1/13 16:48
 */
@Component
public class Task {

  @Resource
  private DataOperationMapper dataOperationMapper;

  @Resource
  private SendHistoryService sendHistoryService;

  @Resource
  private RedisCache redisCache;

  @Resource
  private MissionMapper missionMapper;

  @Resource
  private DataPreAvailableService dataPreAvailableService;

  private static final String INIT_MISSION_REDIS_KEY = "INIT_MISSION_REDIS_KEY";

  private static final String MISSION_FAILED_HISTORY_KEY = "MISSION_FAILED_HISTORY_KEY";

  private static final String MISSION_SUCCESS_HISTORY_KEY = "MISSION_SUCCESS_HISTORY_KEY";

  private static final String CHANGE_MISSION_NORMAL_STATUS_KEY = "CHANGE_MISSION_NORMAL_STATUS_KEY";

  private static final String DATA_INCREMENT = "DATA_INCREMENT";
  private static final String DATA_PRE_INCREMENT = "DATA_PRE_INCREMENT";

  private static final String MISSION_HISTORY_DEFAULT = "MISSION_HISTORY_DEFAULT";



  //批量获取任务返回成功状态更新任务发送历史数据库
  @Scheduled(cron = "0/1 * * * * ?")
  public void getMissionSuccessReturnForUpdate() {
    //查看当前任务是否在执行
    if (!getLock(MISSION_SUCCESS_HISTORY_KEY)) {
      return;
    }
    try {
      List<MissionSuccessRedisMap> list = new ArrayList<>();
      for (int i = 0; i < 100; i++) {
        MissionSuccessRedisMap map = (MissionSuccessRedisMap) redisCache.redisTemplate.opsForList()
            .leftPop(DataOperationServiceImpl.MISSION_SUCCESS_RETURN_KEY);
        if (ObjectUtils.isEmpty(map)) {
          //说明当前没有需要执行的队列
          break;
        }
        List<String> dataSendTableName = map.getDataSendTableName();
        if(!CollectionUtils.isEmpty(dataSendTableName)){
          dataSendTableName.forEach(tableName -> {
            boolean tableExits =   dataOperationMapper.tableIsExits(tableName);
            if(!tableExits){
              dataSendTableName.remove(tableName);
            }
          });
        }
        list.add(map);
      }
      if (CollectionUtils.isEmpty(list)) {
        return;
      }
      Map<String, List<MissionSuccessRedisMap>> collect = list.stream().collect(Collectors.groupingBy(MissionSuccessRedisMap::getTableName));
      for (Entry<String, List<MissionSuccessRedisMap>> value : collect.entrySet()) {
        try {
          dataOperationMapper.updateHistoryMissionSuccessGetDetails(value.getKey(), value.getValue());
        } catch (Exception e) {
          e.printStackTrace();
          for (MissionSuccessRedisMap map : value.getValue()) {
            redisCache.redisTemplate.opsForList().rightPush(DataOperationServiceImpl.MISSION_SUCCESS_RETURN_KEY, map);
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      //释放锁资源
      redisCache.deleteObject(MISSION_SUCCESS_HISTORY_KEY);
    }

  }

  //批量获取任务返回失败状态更新任务发送历史数据库
  @Scheduled(cron = "0/1 * * * * ?")
  public void getMissionFailedReturnForUpdate() {
    //查看当前任务是否在执行
    if (!getLock(MISSION_FAILED_HISTORY_KEY)) {
      return;
    }
    try {
      List<MissionSuccessRedisMap> list = new ArrayList<>();
      for (int i = 0; i < 200; i++) {
        MissionSuccessRedisMap map = (MissionSuccessRedisMap) redisCache.redisTemplate.opsForList()
            .leftPop(DataOperationServiceImpl.MISSION_FAILED_RETURN_KEY);
        if (ObjectUtils.isEmpty(map)) {
          //说明当前没有需要执行的队列
          break;
        }
        list.add(map);
      }
      if (CollectionUtils.isEmpty(list)) {
        return;
      }
      Map<String, List<MissionSuccessRedisMap>> collect = list.stream().collect(Collectors.groupingBy(MissionSuccessRedisMap::getTableName));
      for (Entry<String, List<MissionSuccessRedisMap>> value : collect.entrySet()) {
        try {
          dataOperationMapper.updateHistoryMissionSuccessGetDetails(value.getKey(), value.getValue());
          //dataOperationMapper.updateHistoryMissionFailedGetDetails(value.getKey(), value.getValue());
        } catch (Exception e) {
          for (MissionSuccessRedisMap map : value.getValue()) {
            redisCache.redisTemplate.opsForList().rightPush(DataOperationServiceImpl.MISSION_FAILED_RETURN_KEY, map);
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      //释放锁资源
      redisCache.deleteObject(MISSION_FAILED_HISTORY_KEY);
    }

  }

  private boolean getLock(String redisKey) {
    //boolean flag = Boolean.TRUE.equals(redisCache.redisTemplate.opsForValue().setIfAbsent(redisKey, 1));
    boolean flag = redisCache.hasKey(redisKey);
    //如果获取锁成功,就将锁时间设置为2分钟,防止任务异常退出后没有执行任务结束的释放锁操作导致后面永远无法执行
    if (!flag) {
      flag = Boolean.TRUE.equals(redisCache.redisTemplate.opsForValue().setIfAbsent(redisKey, 1, 2, TimeUnit.MINUTES));
    }
    return flag;
  }

  //批量获取需要初始化任务的任务code
  @Scheduled(cron = "0/10 * * * * ?")
  public void getMissionNeedInitCode() {
    //查看当前任务是否在执行
    if (!getLock(INIT_MISSION_REDIS_KEY)) {
      return;
    }
    try {
      Collection<String> keys = redisCache.keys(RedisConstants.MISSION_NEED_INIT + "*");
      if (CollectionUtils.isEmpty(keys)) {
        return;
      }
      List<String> codes = keys.stream().map(f -> f.split(":")[1]).collect(Collectors.toList());
      List<String> needInitCode = new ArrayList<>();
      for (String code : codes) {
        if (!redisCache.hasKey(RedisConstants.MISSION_NOT_NORMAL_STATE + code)) {
          //判断是否已经成为异常任务,如果不是才需要加入初始化队列
          needInitCode.add(code);
        }
        redisCache.deleteObject(RedisConstants.MISSION_NEED_INIT + code);
      }
      missionMapper.initMissionNormalState(needInitCode);
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      //释放锁资源
      redisCache.deleteObject(INIT_MISSION_REDIS_KEY);
    }
  }

  //批量获取需要初始化任务的任务code
  @Scheduled(cron = "0/1 * * * * ?")
  public void getMissionNeedChangeNotNormal() {
    //查看当前任务是否在执行
    if (!getLock(CHANGE_MISSION_NORMAL_STATUS_KEY)) {
      return;
    }
    try {
      Collection<String> keys = redisCache.keys(RedisConstants.MISSION_NOT_NORMAL_STATE + "*");
      if (CollectionUtils.isEmpty(keys)) {
        return;
      }
      List<String> codes = keys.stream().map(f -> f.split(":")[1]).collect(Collectors.toList());
      List<MissionChangeNotNormalInfo> changeList = new ArrayList<>();
      for (String code : codes) {
        changeList.add(new MissionChangeNotNormalInfo(code, redisCache.getCacheObject(RedisConstants.MISSION_PAGE_FAILED_COUNT + code)));
        redisCache.deleteObject(RedisConstants.MISSION_NOT_NORMAL_STATE + code);
        redisCache.deleteObject(RedisConstants.MISSION_PAGE_FAILED_COUNT + code);
      }
      missionMapper.changeMissionNormalStatusToFalse(changeList);
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      //释放锁资源
      redisCache.deleteObject(CHANGE_MISSION_NORMAL_STATUS_KEY);
    }
  }


  //批量获取Data发送后需要把对应数据表中的数据发送次数累加的dataCode
  @Scheduled(cron = "0/1 * * * * ?")
  public void getDataNeedIncrement() {
    //查看当前任务是否在执行
    if (!getLock(DATA_INCREMENT)) {
      return;
    }
    try {
      List<DataIncrementInfo> dataIncrementInfos = new ArrayList<>();
      for (int i = 0; i < 1000; i++) {
        DataIncrementInfo map = (DataIncrementInfo) redisCache.redisTemplate.opsForList().leftPop(RedisConstants.DATA_SEND_INCREMENT_KEY);
        if (ObjectUtils.isEmpty(map)) {
          break;
        }
        dataIncrementInfos.add(map);
      }
      if (CollectionUtils.isEmpty(dataIncrementInfos)) {
        return;
      }
      Map<String, List<DataIncrementInfo>> tableGroup = dataIncrementInfos.stream().collect(Collectors.groupingBy(DataIncrementInfo::getTableName));
      for (Entry<String, List<DataIncrementInfo>> tableEntry : tableGroup.entrySet()) {
        Map<String, List<DataIncrementInfo>> codeGroup = tableEntry.getValue().stream().collect(Collectors.groupingBy(DataIncrementInfo::getCode));
        List<DataIncrementCodeGroupInfo> dataIncrementCodeGroupInfos = new ArrayList<>();
        for (Entry<String, List<DataIncrementInfo>> codeEntry : codeGroup.entrySet()) {
          dataIncrementCodeGroupInfos.add(new DataIncrementCodeGroupInfo(codeEntry.getKey(), codeEntry.getValue().size()));
        }
        dataOperationMapper.incrementUseCountBatch(tableEntry.getKey(), dataIncrementCodeGroupInfos);
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      //释放锁资源
      redisCache.deleteObject(DATA_INCREMENT);
    }
  }

  //批量扫描未返回任务60分钟后，系统默认将任务历史详情表的Display_Flag=0
//  @Scheduled(cron = "0 0/50 * * * ?")


  @Scheduled(cron = "0 0/60 * * * ?")
//@Scheduled(cron = "0 0/1 * * * ?")
  public void getMissionHistoryDetail() {
    //查看当前任务是否在执行
    if (!getLock(MISSION_HISTORY_DEFAULT)) {
      return;
    }
    try {

      Date now = new Date();
      String startTime = DateUtil.dateToStr(now, DateConstants.DATE_FORMAT_START);
      String endTime = DateUtil.dateToStr(now, DateConstants.DATE_FORMAT_END);

      List<HistoryDataSearchInfo> searchTableList = sendHistoryService.getSearchTableList(SystemFunctionUtil.HISTORY_MISSION_GET_DETAIL, startTime, endTime);
      sendHistoryService.updateMissionHistoryaDetailIsDisplay(searchTableList);

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      //释放锁资源
      redisCache.deleteObject(MISSION_HISTORY_DEFAULT);
    }
  }


//  @Scheduled(cron = "0/1 * * * * ?")
//  public void getPreDataNeedIncrement() {
//    //查看当前任务是否在执行
//    if (!getLock(DATA_PRE_INCREMENT)) {
//      return;
//    }
//    try {
//      List<DataAvailableDataInfo> dataAvailableDataInfos = new ArrayList<>();
//      for (int i = 0; i < 1000; i++) {
//        DataAvailableDataInfo map = (DataAvailableDataInfo) redisCache.redisTemplate.opsForList().leftPop(RedisKeyConstants.DATA_SEND_INCREMENT_PRE_KEY.formatKey());
//        if(ObjectUtils.isEmpty(map)){
//          break;
//        }
//        dataAvailableDataInfos.add(map);
//      }
//      if(CollectionUtils.isEmpty(dataAvailableDataInfos)){
//        return;
//      }
//      dataPreAvailableService.updataAvailableDataBatchByIsInitAndSouceCode(dataAvailableDataInfos);
//
//    } catch (Exception e) {
//      e.printStackTrace();
//    } finally {
//      //释放锁资源
//      redisCache.deleteObject(DATA_PRE_INCREMENT);
//    }
//  }

}
